home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / ccs / ccs-11tl.lha / lbl / jpeg / sources / cjpeg.c next >
Encoding:
C/C++ Source or Header  |  1993-04-30  |  21.6 KB  |  733 lines

  1. /*
  2.  * jcmain.c
  3.  *
  4.  * Copyright (C) 1991, 1992, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains a command-line user interface for the JPEG compressor.
  9.  * It should work on any system with Unix- or MS-DOS-style command lines.
  10.  *
  11.  * Two different command line styles are permitted, depending on the
  12.  * compile-time switch TWO_FILE_COMMANDLINE:
  13.  *    cjpeg [options]  inputfile outputfile
  14.  *    cjpeg [options]  [inputfile]
  15.  * In the second style, output is always to standard output, which you'd
  16.  * normally redirect to a file or pipe to some other program.  Input is
  17.  * either from a named file or from standard input (typically redirected).
  18.  * The second style is convenient on Unix but is unhelpful on systems that
  19.  * don't support pipes.  Also, you MUST use the first style if your system
  20.  * doesn't do binary I/O to stdin/stdout.
  21. %
  22. % Modified:     Jin Guojun - LBL, Image Technology Group
  23. %       Date:   April 14, 1992
  24. %       Goal:   To be easily handled by conversion library - CCS (c)
  25. %        HIPS, FITS, GIF, RLE, SUN-raster, PNM, TIFF, PICT ...
  26. %        can be compressed by cjpeg now, directly displayed by tuner,
  27. %        decompressed to other image type by torle, torast, and color_ps.
  28. %        These type of images can be determined by program `headers'.
  29.  */
  30.  
  31. #include "jinclude.h"
  32. #ifdef INCLUDES_ARE_ANSI
  33. #include <stdlib.h>        /* to declare exit() */
  34. #endif
  35. #include <ctype.h>        /* to declare isupper(), tolower() */
  36. #ifdef NEED_SIGNAL_CATCHER
  37. #include <signal.h>        /* to declare signal() */
  38. #endif
  39. #ifdef USE_SETMODE
  40. #include <fcntl.h>        /* to declare setmode() */
  41. #endif
  42.  
  43. #ifdef THINK_C
  44. #include <console.h>        /* command-line reader for Macintosh */
  45. #endif
  46.  
  47. #ifdef DONT_USE_B_MODE        /* define mode parameters for fopen() */
  48. #define READ_BINARY    "r"
  49. #define WRITE_BINARY    "w"
  50. #else
  51. #define READ_BINARY    "rb"
  52. #define WRITE_BINARY    "wb"
  53. #endif
  54.  
  55. #ifndef EXIT_FAILURE        /* define exit() codes if not provided */
  56. #define EXIT_FAILURE  1
  57. #endif
  58. #ifndef EXIT_SUCCESS
  59. #ifdef VMS
  60. #define EXIT_SUCCESS  1        /* VMS is very nonstandard */
  61. #else
  62. #define EXIT_SUCCESS  0
  63. #endif
  64. #endif
  65.  
  66.  
  67. #include "jversion.h"        /* for version message */
  68.  
  69.  
  70. /*
  71.  * This routine determines what format the input file is,
  72.  * and selects the appropriate input-reading module.
  73.  *
  74.  * To determine which family of input formats the file belongs to,
  75.  * we may look only at the first byte of the file, since C does not
  76.  * guarantee that more than one character can be pushed back with ungetc.
  77.  * Looking at additional bytes would require one of these approaches:
  78.  *     1) assume we can fseek() the input file (fails for piped input);
  79.  *     2) assume we can push back more than one character (works in
  80.  *        some C implementations, but unportable);
  81.  *     3) provide our own buffering as is done in djpeg (breaks input readers
  82.  *        that want to use stdio directly, such as the RLE library);
  83.  * or  4) don't put back the data, and modify the input_init methods to assume
  84.  *        they start reading after the start of file (also breaks RLE library).
  85.  * #1 is attractive for MS-DOS but is untenable on Unix.
  86.  *
  87.  * The most portable solution for file types that can't be identified by their
  88.  * first byte is to make the user tell us what they are.  This is also the
  89.  * only approach for "raw" file types that contain only arbitrary values.
  90.  * We presently apply this method for Targa files.  Most of the time Targa
  91.  * files start with 0x00, so we recognize that case.  Potentially, however,
  92.  * a Targa file could start with any byte value (byte 0 is the length of the
  93.  * seldom-used ID field), so we provide a switch to force Targa input mode.
  94.  */
  95.  
  96. static boolean is_targa;    /* records user -targa switch */
  97.  
  98. LOCAL int    input_row_pos;
  99. U_IMAGE uimg;
  100.  
  101. void
  102. input_init(compress_info_ptr cinfo)
  103. {
  104. register U_IMAGE*    img = cinfo->img;
  105.     (*img->header_handle)(HEADER_READ, img, 0, 0, 0);
  106.     cinfo->image_width = img->width;
  107.     cinfo->image_height = img->height;
  108.     cinfo->data_precision = 8;
  109.     switch(img->color_form) {
  110.     case CFM_SGF:
  111.          cinfo->in_color_space = CS_GRAYSCALE;
  112.         cinfo->input_components = img->dpy_channels;
  113.         break;
  114.     case CFM_ILL:
  115.     default:
  116.         cinfo->in_color_space = CS_RGB;
  117.         cinfo->input_components = 3;
  118.     }
  119. }
  120.  
  121. void
  122. get_input_row(compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  123. {
  124. register U_IMAGE*    img = cinfo->img;
  125. register int    col = img->width;
  126. register JSAMPROW    pr = pixel_row[0], pg = pixel_row[1], pb = pixel_row[2];
  127. register byte    *p = (byte*) img->src + input_row_pos * img->dpy_channels * col;
  128.     switch(img->color_form)    {
  129.     case CFM_SCF:
  130.         while (col--)    {
  131.         register int    c = *p++;
  132.             *pr++ = reg_cmap[0][c];
  133.             *pg++ = reg_cmap[1][c];
  134.             *pb++ = reg_cmap[2][c];
  135.         }
  136.         break;
  137.     case CFM_SEPLANE:
  138.         mesg("warning -- not ready\n");
  139.     case CFM_ILC:
  140.         snf_to_rle(pr, p, col, 3, NULL); /* ? */
  141.         break;
  142.     case CFM_ILL:
  143.         memcpy(pb, p+(col<<1), col);
  144.         memcpy(pg, p+col, col);
  145.     case CFM_SGF:
  146.         memcpy(pr, p, col);
  147.         break;
  148.     default:    prgmerr('f', "strange color form %d", img->color_form);
  149.     }
  150.     input_row_pos++;
  151. }
  152.  
  153. LOCAL void
  154. input_term(compress_info_ptr cinfo, int term)
  155. {
  156.     if (term)    free(cinfo->img->src);
  157.     else    input_row_pos = 0;
  158. }
  159.  
  160.  
  161. LOCAL void
  162. select_file_type (compress_info_ptr cinfo)
  163. {
  164.     if (is_targa) {
  165. #ifdef TARGA_SUPPORTED
  166.         jselrtarga(cinfo);
  167. #else
  168.         ERREXIT(cinfo->emethods, "Targa support was not compiled");
  169. #endif
  170.     } else    {
  171.         cinfo->methods->input_init = input_init;
  172.         cinfo->methods->get_input_row = get_input_row;
  173.         cinfo->methods->input_term = input_term;
  174.     }
  175. }
  176.  
  177.  
  178. /*
  179.  * This routine gets control after the input file header has been read.
  180.  * It must determine what output JPEG file format is to be written,
  181.  * and make any other compression parameter changes that are desirable.
  182.  */
  183.  
  184. METHODDEF void
  185. c_ui_method_selection (compress_info_ptr cinfo)
  186. {
  187.   /* If the input is gray scale, generate a monochrome JPEG file. */
  188.   if (cinfo->in_color_space == CS_GRAYSCALE)
  189.     j_monochrome_default(cinfo);
  190.   /* For now, always select JFIF output format. */
  191. #ifdef JFIF_SUPPORTED
  192.   jselwjfif(cinfo);
  193. #else
  194.   You shoulda defined JFIF_SUPPORTED.   /* deliberate syntax error */
  195. #endif
  196. }
  197.  
  198.  
  199. /*
  200.  * Signal catcher to ensure that temporary files are removed before aborting.
  201.  * NB: for Amiga Manx C this is actually a global routine named _abort();
  202.  * see -Dsignal_catcher=_abort in CFLAGS.  Talk about bogus...
  203.  */
  204.  
  205. #ifdef NEED_SIGNAL_CATCHER
  206.  
  207. static external_methods_ptr emethods; /* for access to free_all */
  208.  
  209. GLOBAL void
  210. signal_catcher (int signum)
  211. {
  212.   if (emethods != NULL) {
  213.     emethods->trace_level = 0;    /* turn off trace output */
  214.     (*emethods->free_all) ();    /* clean up memory allocation & temp files */
  215.   }
  216.   exit(EXIT_FAILURE);
  217. }
  218.  
  219. #endif
  220.  
  221.  
  222. /*
  223.  * Optional routine to display a percent-done figure on stderr.
  224.  * See jcdeflts.c for explanation of the information used.
  225.  */
  226.  
  227. #ifdef PROGRESS_REPORT
  228.  
  229. METHODDEF void
  230. progress_monitor (compress_info_ptr cinfo, long loopcounter, long looplimit)
  231. {
  232.   if (cinfo->total_passes > 1) {
  233.     fprintf(stderr, "\rPass %d/%d: %3d%% ",
  234.         cinfo->completed_passes+1, cinfo->total_passes,
  235.         (int) (loopcounter*100L/looplimit));
  236.   } else {
  237.     fprintf(stderr, "\r %3d%% ",
  238.         (int) (loopcounter*100L/looplimit));
  239.   }
  240.   fflush(stderr);
  241. }
  242.  
  243. #endif
  244.  
  245.  
  246. /*
  247.  * Argument-parsing code.
  248.  * The switch parser is designed to be useful with DOS-style command line
  249.  * syntax, ie, intermixed switches and file names, where only the switches
  250.  * to the left of a given file name affect processing of that file.
  251.  * The main program in this file doesn't actually use this capability...
  252.  */
  253.  
  254.  
  255. static char * progname;        /* program name for error messages */
  256.  
  257.  
  258. LOCAL void
  259. usage (void)
  260. /* complain about bad command line */
  261. {
  262.   fprintf(stderr, "usage: %s [switches] ", progname);
  263. #ifdef TWO_FILE_COMMANDLINE
  264.   fprintf(stderr, "inputfile outputfile\n");
  265. #else
  266.   fprintf(stderr, "[inputfile]\n");
  267. #endif
  268.  
  269.   fprintf(stderr, "Switches (names may be abbreviated):\n");
  270.   fprintf(stderr, "  -quality N     Compression quality (0..100; 5-95 is useful range)\n");
  271.   fprintf(stderr, "  -grayscale     Create monochrome JPEG file\n");
  272. #ifdef ENTROPY_OPT_SUPPORTED
  273.   fprintf(stderr, "  -optimize      Optimize Huffman table (smaller file, but slow compression)\n");
  274. #endif
  275. #ifdef TARGA_SUPPORTED
  276.   fprintf(stderr, "  -targa         Input file is Targa format (usually not needed)\n");
  277. #endif
  278.   fprintf(stderr, "Switches for advanced users:\n");
  279.   fprintf(stderr, "  -restart N     Set restart interval in rows, or in blocks with B\n");
  280.   fprintf(stderr, "  -smooth N      Smooth dithered input (N=1..100 is strength)\n");
  281.   fprintf(stderr, "  -maxmemory N   Maximum memory to use (in kbytes)\n");
  282.   fprintf(stderr, "  -verbose  or  -debug   Emit debug output\n");
  283.   fprintf(stderr, "Switches for wizards:\n");
  284. #ifdef C_ARITH_CODING_SUPPORTED
  285.   fprintf(stderr, "  -arithmetic    Use arithmetic coding\n");
  286. #endif
  287. #ifdef C_MULTISCAN_FILES_SUPPORTED
  288.   fprintf(stderr, "  -nointerleave  Create noninterleaved JPEG file\n");
  289. #endif
  290.   fprintf(stderr, "  -qtables file  Use quantization tables given in file\n");
  291.   fprintf(stderr, "  -sample HxV[,...]  Set JPEG sampling factors\n");
  292.   exit(EXIT_FAILURE);
  293. }
  294.  
  295.  
  296. LOCAL boolean
  297. keymatch (char * arg, const char * keyword, int minchars)
  298. /* Case-insensitive matching of (possibly abbreviated) keyword switches. */
  299. /* keyword is the constant keyword (must be lower case already), */
  300. /* minchars is length of minimum legal abbreviation. */
  301. {
  302.   register int ca, ck;
  303.   register int nmatched = 0;
  304.  
  305.   while ((ca = *arg++) != '\0') {
  306.     if ((ck = *keyword++) == '\0')
  307.       return FALSE;        /* arg longer than keyword, no good */
  308.     if (isupper(ca))        /* force arg to lcase (assume ck is already) */
  309.       ca = tolower(ca);
  310.     if (ca != ck)
  311.       return FALSE;        /* no good */
  312.     nmatched++;            /* count matched characters */
  313.   }
  314.   /* reached end of argument; fail if it's too short for unique abbrev */
  315.   if (nmatched < minchars)
  316.     return FALSE;
  317.   return TRUE;            /* A-OK */
  318. }
  319.  
  320.  
  321. LOCAL int
  322. qt_getc (FILE * file)
  323. /* Read next char, skipping over any comments (# to end of line) */
  324. /* A comment/newline sequence is returned as a newline */
  325. {
  326.   register int ch;
  327.   
  328.   ch = getc(file);
  329.   if (ch == '#') {
  330.     do {
  331.       ch = getc(file);
  332.     } while (ch != '\n' && ch != EOF);
  333.   }
  334.   return ch;
  335. }
  336.  
  337.  
  338. LOCAL long
  339. read_qt_integer (FILE * file)
  340. /* Read an unsigned decimal integer from a quantization-table file */
  341. /* Swallows one trailing character after the integer */
  342. {
  343.   register int ch;
  344.   register long val;
  345.   
  346.   /* Skip any leading whitespace, detect EOF */
  347.   do {
  348.     ch = qt_getc(file);
  349.     if (ch == EOF)
  350.       return EOF;
  351.   } while (isspace(ch));
  352.   
  353.   if (! isdigit(ch)) {
  354.     fprintf(stderr, "%s: bogus data in quantization file\n", progname);
  355.     exit(EXIT_FAILURE);
  356.   }
  357.  
  358.   val = ch - '0';
  359.   while (ch = qt_getc(file), isdigit(ch)) {
  360.     val *= 10;
  361.     val += ch - '0';
  362.   }
  363.   return val;
  364. }
  365.  
  366.  
  367. LOCAL void
  368. read_quant_tables (compress_info_ptr cinfo, char * filename, int scale_factor)
  369. /* Read a set of quantization tables from the specified file.
  370.  * The file is plain ASCII text: decimal numbers with whitespace between.
  371.  * Comments preceded by '#' may be included in the file.
  372.  * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
  373.  * The tables are implicitly numbered 0,1,etc.
  374.  */
  375. {
  376.   /* ZIG[i] is the zigzag-order position of the i'th element of a DCT block */
  377.   /* read in natural order (left to right, top to bottom). */
  378.   static const short ZIG[DCTSIZE2] = {
  379.      0,  1,  5,  6, 14, 15, 27, 28,
  380.      2,  4,  7, 13, 16, 26, 29, 42,
  381.      3,  8, 12, 17, 25, 30, 41, 43,
  382.      9, 11, 18, 24, 31, 40, 44, 53,
  383.     10, 19, 23, 32, 39, 45, 52, 54,
  384.     20, 22, 33, 38, 46, 51, 55, 60,
  385.     21, 34, 37, 47, 50, 56, 59, 61,
  386.     35, 36, 48, 49, 57, 58, 62, 63
  387.     };
  388.   FILE * fp;
  389.   int tblno, i;
  390.   long val;
  391.   QUANT_TBL table;
  392.  
  393.   if ((fp = fopen(filename, "r")) == NULL) {
  394.     fprintf(stderr, "%s: can't open %s\n", progname, filename);
  395.     exit(EXIT_FAILURE);
  396.   }
  397.   tblno = 0;
  398.  
  399.   while ((val = read_qt_integer(fp)) != EOF) { /* read 1st element of table */
  400.     if (tblno >= NUM_QUANT_TBLS) {
  401.       fprintf(stderr, "%s: too many tables in file %s\n", progname, filename);
  402.       exit(EXIT_FAILURE);
  403.     }
  404.     table[0] = (QUANT_VAL) val;
  405.     for (i = 1; i < DCTSIZE2; i++) {
  406.       if ((val = read_qt_integer(fp)) == EOF) {
  407.     fprintf(stderr, "%s: incomplete table in file %s\n", progname, filename);
  408.     exit(EXIT_FAILURE);
  409.       }
  410.       table[ZIG[i]] = (QUANT_VAL) val;
  411.     }
  412.     j_add_quant_table(cinfo, tblno, table, scale_factor, FALSE);
  413.     tblno++;
  414.   }
  415.  
  416.   fclose(fp);
  417. }
  418.  
  419.  
  420. LOCAL void
  421. set_sample_factors (compress_info_ptr cinfo, char *arg)
  422. /* Process a sample-factors parameter string, of the form */
  423. /*     HxV[,HxV,...]    */
  424. {
  425. #define MAX_COMPONENTS 4    /* # of comp_info slots made by jcdeflts.c */
  426.   int ci, val1, val2;
  427.   char ch1, ch2;
  428.  
  429.   for (ci = 0; ci < MAX_COMPONENTS; ci++) {
  430.     if (*arg) {
  431.       ch2 = ',';        /* if not set by sscanf, will be ',' */
  432.       if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
  433.     usage();
  434.       if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',')
  435.     usage();        /* syntax check */
  436.       if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) {
  437.     fprintf(stderr, "JPEG sampling factors must be 1..4\n");
  438.     exit(EXIT_FAILURE);
  439.       }
  440.       cinfo->comp_info[ci].h_samp_factor = val1;
  441.       cinfo->comp_info[ci].v_samp_factor = val2;
  442.       while (*arg && *arg++ != ',') /* advance to next segment of arg string */
  443.     ;
  444.     } else {
  445.       /* reached end of parameter, set remaining components to 1x1 sampling */
  446.       cinfo->comp_info[ci].h_samp_factor = 1;
  447.       cinfo->comp_info[ci].v_samp_factor = 1;
  448.     }
  449.   }
  450. }
  451.  
  452.  
  453. LOCAL int
  454. parse_switches (compress_info_ptr cinfo, int last_file_arg_seen,
  455.         int argc, char **argv)
  456. /* Initialize cinfo with default switch settings, then parse option switches.
  457.  * Returns argv[] index of first file-name argument (== argc if none).
  458.  * Any file names with indexes <= last_file_arg_seen are ignored;
  459.  * they have presumably been processed in a previous iteration.
  460.  * (Pass 0 for last_file_arg_seen on the first or only iteration.)
  461.  */
  462. {
  463.   int argn;
  464.   char * arg;
  465.   char * qtablefile = NULL;    /* saves -qtables filename if any */
  466.   int q_scale_factor = 100;    /* default to no scaling for -qtables */
  467.  
  468.   /* (Re-)initialize the system-dependent error and memory managers. */
  469.   jselerror(cinfo->emethods);    /* error/trace message routines */
  470.   jselmemmgr(cinfo->emethods);    /* memory allocation routines */
  471.   cinfo->methods->c_ui_method_selection = c_ui_method_selection;
  472.  
  473.   /* Now OK to enable signal catcher. */
  474. #ifdef NEED_SIGNAL_CATCHER
  475.   emethods = cinfo->emethods;
  476. #endif
  477.  
  478.   /* Set up default JPEG parameters. */
  479.   /* Note that default -quality level here need not, and does not,
  480.    * match the default scaling for an explicit -qtables argument.
  481.    */
  482.   j_c_defaults(cinfo, 75, FALSE); /* default quality level = 75 */
  483.   is_targa = FALSE;
  484.  
  485.   /* Scan command line options, adjust parameters */
  486.  
  487.   for (argn = 1; argn < argc; argn++) {
  488.     arg = argv[argn];
  489.     if (*arg != '-') {
  490.       /* Not a switch, must be a file name argument */
  491.       if (argn <= last_file_arg_seen)
  492.     continue;        /* ignore it if previously processed */
  493.       break;            /* else done parsing switches */
  494.     }
  495.     arg++;            /* advance past switch marker character */
  496.  
  497.     if (keymatch(arg, "arithmetic", 1)) {
  498.       /* Use arithmetic coding. */
  499. #ifdef C_ARITH_CODING_SUPPORTED
  500.       cinfo->arith_code = TRUE;
  501. #else
  502.       fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
  503.           progname);
  504.       exit(EXIT_FAILURE);
  505. #endif
  506.  
  507.     } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
  508.       /* Enable debug printouts. */
  509.       /* On first -d, print version identification */
  510.       if (last_file_arg_seen == 0 && cinfo->emethods->trace_level == 0)
  511.     fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
  512.         JVERSION, JCOPYRIGHT);
  513.       cinfo->emethods->trace_level++;
  514.  
  515.     } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
  516.       /* Force a monochrome JPEG file to be generated. */
  517.       j_monochrome_default(cinfo);
  518.  
  519.     } else if (keymatch(arg, "maxmemory", 1)) {
  520.       /* Maximum memory in Kb (or Mb with 'm'). */
  521.       long lval;
  522.       char ch = 'x';
  523.  
  524.       if (++argn >= argc)    /* advance to next argument */
  525.     usage();
  526.       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
  527.     usage();
  528.       if (ch == 'm' || ch == 'M')
  529.     lval *= 1000L;
  530.       cinfo->emethods->max_memory_to_use = lval * 1000L;
  531.  
  532.     } else if (keymatch(arg, "nointerleave", 3)) {
  533.       /* Create noninterleaved file. */
  534. #ifdef C_MULTISCAN_FILES_SUPPORTED
  535.       cinfo->interleave = FALSE;
  536. #else
  537.       fprintf(stderr, "%s: sorry, multiple-scan support was not compiled\n",
  538.           progname);
  539.       exit(EXIT_FAILURE);
  540. #endif
  541.  
  542.     } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
  543.       /* Enable entropy parm optimization. */
  544. #ifdef ENTROPY_OPT_SUPPORTED
  545.       cinfo->optimize_coding = TRUE;
  546. #else
  547.       fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
  548.           progname);
  549.       exit(EXIT_FAILURE);
  550. #endif
  551.  
  552.     } else if (keymatch(arg, "quality", 1)) {
  553.       /* Quality factor (quantization table scaling factor). */
  554.       int val;
  555.  
  556.       if (++argn >= argc)    /* advance to next argument */
  557.     usage();
  558.       if (sscanf(argv[argn], "%d", &val) != 1)
  559.     usage();
  560.       /* Set quantization tables (will be overridden if -qtables also given).
  561.        * Note: we make force_baseline FALSE.
  562.        * This means non-baseline JPEG files can be created with low Q values.
  563.        * To ensure only baseline files are generated, pass TRUE instead.
  564.        */
  565.       j_set_quality(cinfo, val, FALSE);
  566.       /* Change scale factor in case -qtables is present. */
  567.       q_scale_factor = j_quality_scaling(val);
  568.  
  569.     } else if (keymatch(arg, "qtables", 2)) {
  570.       /* Quantization tables fetched from file. */
  571.       if (++argn >= argc)    /* advance to next argument */
  572.     usage();
  573.       qtablefile = argv[argn];
  574.       /* we postpone actually reading the file in case -quality comes later */
  575.  
  576.     } else if (keymatch(arg, "restart", 1)) {
  577.       /* Restart interval in MCU rows (or in MCUs with 'b'). */
  578.       long lval;
  579.       char ch = 'x';
  580.  
  581.       if (++argn >= argc)    /* advance to next argument */
  582.     usage();
  583.       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
  584.     usage();
  585.       if (lval < 0 || lval > 65535L)
  586.     usage();
  587.       if (ch == 'b' || ch == 'B')
  588.     cinfo->restart_interval = (UINT16) lval;
  589.       else
  590.     cinfo->restart_in_rows = (int) lval;
  591.  
  592.     } else if (keymatch(arg, "sample", 2)) {
  593.       /* Set sampling factors. */
  594.       if (++argn >= argc)    /* advance to next argument */
  595.     usage();
  596.       set_sample_factors(cinfo, argv[argn]);
  597.  
  598.     } else if (keymatch(arg, "smooth", 2)) {
  599.       /* Set input smoothing factor. */
  600.       int val;
  601.  
  602.       if (++argn >= argc)    /* advance to next argument */
  603.     usage();
  604.       if (sscanf(argv[argn], "%d", &val) != 1)
  605.     usage();
  606.       if (val < 0 || val > 100)
  607.     usage();
  608.       cinfo->smoothing_factor = val;
  609.  
  610.     } else if (keymatch(arg, "targa", 1)) {
  611.       /* Input file is Targa format. */
  612.       is_targa = TRUE;
  613.  
  614.     } else {
  615.       usage();            /* bogus switch */
  616.     }
  617.   }
  618.  
  619.   /* Post-switch-scanning cleanup */
  620.  
  621.   if (qtablefile != NULL)    /* process -qtables if it was present */
  622.     read_quant_tables(cinfo, qtablefile, q_scale_factor);
  623.  
  624.   return argn;            /* return index of next arg (file name) */
  625. }
  626.  
  627.  
  628. /*
  629.  * The main program.
  630.  */
  631.  
  632. GLOBAL int
  633. main (int argc, char **argv)
  634. {
  635.   struct Compress_info_struct cinfo;
  636.   struct Compress_methods_struct c_methods;
  637.   struct External_methods_struct e_methods;
  638.   int file_index;
  639.  
  640.   /* On Mac, fetch a command line. */
  641. #ifdef THINK_C
  642.   argc = ccommand(&argv);
  643. #endif
  644.  
  645.   progname = argv[0];
  646.  
  647.     format_init(&uimg, IMAGE_INIT_TYPE, RLE, JPEG, progname, "M5-2");
  648.     uimg.color_dpy = True;
  649.     cinfo.img = &uimg;
  650.  
  651.   /* Set up links to method structures. */
  652.   cinfo.methods = &c_methods;
  653.   cinfo.emethods = &e_methods;
  654.  
  655.   /* Install, but don't yet enable signal catcher. */
  656. #ifdef NEED_SIGNAL_CATCHER
  657.   emethods = NULL;
  658.   signal(SIGINT, signal_catcher);
  659. #ifdef SIGTERM            /* not all systems have SIGTERM */
  660.   signal(SIGTERM, signal_catcher);
  661. #endif
  662. #endif
  663.  
  664.   /* Scan command line: set up compression parameters, input & output files. */
  665.  
  666.   file_index = parse_switches(&cinfo, 0, argc, argv);
  667.  
  668. #ifdef TWO_FILE_COMMANDLINE
  669.  
  670.   if (file_index != argc-2) {
  671.     fprintf(stderr, "%s: must name one input and one output file\n", progname);
  672.     usage();
  673.   }
  674.   if ((cinfo.input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
  675.     fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
  676.     exit(EXIT_FAILURE);
  677.   }
  678.   if ((cinfo.output_file = fopen(argv[file_index+1], WRITE_BINARY)) == NULL) {
  679.     fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index+1]);
  680.     exit(EXIT_FAILURE);
  681.   }
  682.  
  683. #else /* not TWO_FILE_COMMANDLINE -- use Unix style */
  684.  
  685.   cinfo.input_file = stdin;    /* default input file */
  686.   cinfo.output_file = stdout;    /* always the output file */
  687.  
  688. #ifdef USE_SETMODE        /* need to hack file mode? */
  689.   setmode(fileno(stdin), O_BINARY);
  690.   setmode(fileno(stdout), O_BINARY);
  691. #endif
  692.  
  693.   if (file_index < argc-1) {
  694.     fprintf(stderr, "%s: only one input file\n", progname);
  695.     usage();
  696.   }
  697.   if (file_index < argc) {
  698.     if ((cinfo.input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
  699.       fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
  700.       exit(EXIT_FAILURE);
  701.     }
  702.     uimg.IN_FP = cinfo.input_file;
  703.   }
  704.  
  705. #endif /* TWO_FILE_COMMANDLINE */
  706.  
  707. io_test(fileno(in_fp), usage(progname));
  708.  
  709.   /* Figure out the input file format, and set up to read it. */
  710.   select_file_type(&cinfo);
  711.  
  712. #ifdef PROGRESS_REPORT
  713.   /* Start up progress display, unless trace output is on */
  714.   if (e_methods.trace_level == 0)
  715.     c_methods.progress_monitor = progress_monitor;
  716. #endif
  717.  
  718.   /* Do it to it! */
  719.   jpeg_compress(&cinfo);
  720.  
  721. #ifdef PROGRESS_REPORT
  722.   /* Clear away progress display */
  723.   if (e_methods.trace_level == 0) {
  724.     fprintf(stderr, "\r                \r");
  725.     fflush(stderr);
  726.   }
  727. #endif
  728.  
  729.   /* All done. */
  730.   exit(EXIT_SUCCESS);
  731.   return 0;            /* suppress no-return-value warnings */
  732. }
  733.